<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">
  <link rel="manifest" href="/images/manifest.json">
  <meta name="msapplication-config" content="/images/browserconfig.xml">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css">
  <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/pace-js@1/themes/blue/pace-theme-minimal.css">
  <script src="//cdn.jsdelivr.net/npm/pace-js@1/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"daydaychen.github.io","root":"/","scheme":"Gemini","version":"7.7.2","exturl":false,"sidebar":{"position":"right","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":"mac"},"back2top":{"enable":true,"sidebar":true,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":true,"lazyload":true,"pangu":true,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":true,"nav":null,"activeClass":"valine"},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":true,"preload":false},"motion":{"enable":true,"async":true,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.xml"};
  </script>

  <meta name="description" content="this is a desc.">
<meta property="og:type" content="website">
<meta property="og:title" content="宁静致远">
<meta property="og:url" content="daydaychen.github.io/page/2/index.html">
<meta property="og:site_name" content="宁静致远">
<meta property="og:description" content="this is a desc.">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="CT">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="daydaychen.github.io/page/2/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : true,
    isPost : false
  };
</script>

  <title>宁静致远</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <div>
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">宁静致远</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
        <p class="site-subtitle">this is a subtitle.</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>


<nav class="site-nav">
  
  <ul id="menu" class="menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-fw fa-home"></i>首页</a>

  </li>
        <li class="menu-item menu-item-about">

    <a href="/about/" rel="section"><i class="fa fa-fw fa-user"></i>关于</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/tags/" rel="section"><i class="fa fa-fw fa-tags"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/categories/" rel="section"><i class="fa fa-fw fa-th"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-fw fa-archive"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>

</nav>
  <div class="site-search">
    <div class="popup search-popup">
    <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocorrect="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result"></div>

</div>
<div class="search-pop-overlay"></div>

  </div>
</div>
    </header>

    


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content">
            

  <div class="posts-expand">
        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E5%8D%8F%E7%A8%8B/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E5%8D%8F%E7%A8%8B/" class="post-title-link" itemprop="url">python协程</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:15:25" itemprop="dateCreated datePublished" datetime="2020-03-06T14:15:25+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/02-%E5%A4%9A%E4%BB%BB%E5%8A%A1-%E5%8D%8F%E7%A8%8B/" class="post-meta-item leancloud_visitors" data-flag-title="python协程" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="协程"><a href="#协程" class="headerlink" title="协程"></a>协程</h4><blockquote>
<p>生成器 迭代器 装饰器 Python三大器</p>
</blockquote>
<blockquote>
<p>迭代器 -&gt; 生成器 -&gt; yield -&gt; greenlet -&gt; gevent</p>
</blockquote>
<h4 id="迭代器"><a href="#迭代器" class="headerlink" title="迭代器"></a>迭代器</h4><p>迭代时访问集合元素的一种方式，迭代器是一个可以记住遍历的位置的对象，迭代器对象从集合的第一个元素开始访问，直到所有的元素被访问完结束。迭代器只能往前不会后退。</p>
<ol>
<li>可迭代对象</li>
</ol>
<p>对list、tuple、str、dict、集合等类型的数据使用for…in…的循环语法从其中依次拿到数据进行使用，我们把这样的过程称为遍历，也叫<strong>迭代</strong>。</p>
<p>但是，是否所有的数据类型都可以放到for…in…的语句中，然后让for…in…每次从中取出一条数据供我们使用，即供我们迭代吗？</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">from collections import Iterable</span><br><span class="line"></span><br><span class="line">isinstance([11, 22, 33], Iterable)</span><br><span class="line">-&gt; True</span><br><span class="line"></span><br><span class="line">isinstance((11, 22, 33), Iterable)</span><br><span class="line">-&gt; True</span><br><span class="line"></span><br><span class="line">isinstance(100, Iterable)</span><br><span class="line">-&gt; False</span><br></pre></td></tr></table></figure>
<h5 id="类的迭代、迭代器的实现"><a href="#类的迭代、迭代器的实现" class="headerlink" title="类的迭代、迭代器的实现"></a>类的迭代、迭代器的实现</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">from collections import Iterable</span><br><span class="line">from collections import Iterator</span><br><span class="line"></span><br><span class="line">class Classmate(object):</span><br><span class="line">    def __init__(self):</span><br><span class="line">        self.names &#x3D; list()</span><br><span class="line">        self.current_num &#x3D; 0</span><br><span class="line">        </span><br><span class="line">    def add(self, name):</span><br><span class="line">        self.names.append(name)</span><br><span class="line">    </span><br><span class="line">    def __iter__(self):</span><br><span class="line">        &#39;&#39;&#39;如果想要一个对象成为一个可以迭代的对象，即可以使用for，那么必须实现__iter__方法&#39;&#39;&#39;</span><br><span class="line">        return self</span><br><span class="line">    </span><br><span class="line">    def __next__(self):</span><br><span class="line">         &#39;&#39;&#39;返回调用值&#39;&#39;&#39;</span><br><span class="line">        if self.current_num &lt; len(self.names):</span><br><span class="line">            ret &#x3D; self.names[self.current_num]</span><br><span class="line">            self.current_num +&#x3D; 1</span><br><span class="line">            return ret</span><br><span class="line">        else:</span><br><span class="line">            raise StopIteration</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">classmate &#x3D; Classmate()</span><br><span class="line"></span><br><span class="line">classmate.add(&quot;张三&quot;)</span><br><span class="line">classmate.add(&quot;李四&quot;)</span><br><span class="line">classmate.add(&quot;王五&quot;)</span><br><span class="line"></span><br><span class="line"># print(&quot;判断classmate是否是可以迭代的对象：&quot;,isinstance(classmate, Iterable))</span><br><span class="line"># classmate_iterator &#x3D; iter(classmate)</span><br><span class="line"># print(&quot;判断classmate_iterator是否是迭代器：&quot;,isinstance(classmate_iterator, Iterator)</span><br><span class="line"></span><br><span class="line">for name in classmate:</span><br><span class="line">    print(name)</span><br></pre></td></tr></table></figure>
<h5 id="Fibonacci的迭代器实现"><a href="#Fibonacci的迭代器实现" class="headerlink" title="Fibonacci的迭代器实现"></a>Fibonacci的迭代器实现</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">class Fibonacci(object):</span><br><span class="line">    def __init__(self, all_num):</span><br><span class="line">        self.all_num &#x3D; all_num</span><br><span class="line">        self.current_num &#x3D; 0</span><br><span class="line">        self.a &#x3D; 0</span><br><span class="line">        self.b &#x3D; 1</span><br><span class="line">    </span><br><span class="line">    def __iter__(self):</span><br><span class="line">        return self</span><br><span class="line">        </span><br><span class="line">    def __next__(self):</span><br><span class="line">        if self.current_num &lt; self.all_num:</span><br><span class="line">            ret &#x3D; self.a</span><br><span class="line">            </span><br><span class="line">            self.a, self.b &#x3D; self.b, self.a+self.b</span><br><span class="line">            self.current_num +&#x3D; 1</span><br><span class="line">            </span><br><span class="line">            return ret</span><br><span class="line">        else:</span><br><span class="line">            raise StopIteration</span><br><span class="line"></span><br><span class="line">fibo &#x3D; Fibonacci(10)</span><br><span class="line"></span><br><span class="line">for num in fibo:</span><br><span class="line">    print(num)</span><br></pre></td></tr></table></figure>

<h5 id="并不是只有for循环能接受可迭代对象"><a href="#并不是只有for循环能接受可迭代对象" class="headerlink" title="并不是只有for循环能接受可迭代对象"></a>并不是只有for循环能接受可迭代对象</h5><p>除了for循环能接受可迭代对象，list、tuple等也能接受</p>
<p><strong>iter</strong>()  -&gt;  <strong>next</strong>() -&gt; return </p>
<h4 id="生成器"><a href="#生成器" class="headerlink" title="生成器"></a>生成器</h4><p>生成器是一个特殊的迭代器</p>
<h5 id="应用1"><a href="#应用1" class="headerlink" title="应用1"></a>应用1</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">nums &#x3D; [x*2 for x in range(10)]</span><br><span class="line">-&gt; [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]</span><br><span class="line"></span><br><span class="line">nums &#x3D; (x*2 for x in range(10))</span><br><span class="line">-&gt; &lt;generator object &lt;genexpr&gt; at 0x7f7ec7071938&gt;</span><br></pre></td></tr></table></figure>

<p>列表推导式生成一个列表<br>生成器生成一个对象，不占用内存空间,可通过for循环调用</p>
<h5 id="应用2"><a href="#应用2" class="headerlink" title="应用2"></a>应用2</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">def create_num(all_num):</span><br><span class="line">    a, b &#x3D; 0, 1</span><br><span class="line">    current_num &#x3D; 0</span><br><span class="line">    while current_num &lt; all_num：</span><br><span class="line">        yield a     #如果一个函数中有yield语句，那么这个就不再是函数，而是一个生成器模板</span><br><span class="line">        a, b &#x3D; b, a+b</span><br><span class="line">        current_num +&#x3D; 1</span><br><span class="line"># 如果在调用create_num的时候，发现这个函数中由yield，那么此时不是调用函数，而是创建一个生成器对象。</span><br><span class="line">obj &#x3D; create_num(10)</span><br><span class="line"></span><br><span class="line">for num in obj:</span><br><span class="line">    print(num)</span><br></pre></td></tr></table></figure>

<h5 id="yield生成器获取return值"><a href="#yield生成器获取return值" class="headerlink" title="yield生成器获取return值"></a>yield生成器获取return值</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">def create_num(all_num):</span><br><span class="line">    a, b &#x3D; 0, 1</span><br><span class="line">    current_num &#x3D; 0</span><br><span class="line">    while current_num &lt; all_num:</span><br><span class="line">        yield a</span><br><span class="line">        a, b &#x3D; b, a+b</span><br><span class="line">        current_num +&#x3D; 1</span><br><span class="line">    return &quot;ok....&quot;</span><br><span class="line">    </span><br><span class="line">obj &#x3D; create_num(20)</span><br><span class="line"></span><br><span class="line">while True:</span><br><span class="line">    try:</span><br><span class="line">        ret &#x3D; next(obj)</span><br><span class="line">        print(ret)</span><br><span class="line">    except Exception as ret:</span><br><span class="line">        print(ret.value)</span><br><span class="line">        break</span><br></pre></td></tr></table></figure>

<h5 id="send-传递参数"><a href="#send-传递参数" class="headerlink" title="send()传递参数"></a>send()传递参数</h5><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">def create_num(all_num):</span><br><span class="line">    a, b &#x3D; 0, 1</span><br><span class="line">    current_num &#x3D; 0</span><br><span class="line">    while current_num &lt; all_num:</span><br><span class="line">        ret &#x3D; yield a   # 右侧语句执行暂停，传参给next()</span><br><span class="line">        # send()将参数传过来，程序从暂停处开始执行，将传过来的参数赋给ret</span><br><span class="line">        print(&quot;ret:&quot;, ret)</span><br><span class="line">        a, b &#x3D; b, a+b</span><br><span class="line">        current_num +&#x3D; 1</span><br><span class="line">    </span><br><span class="line">obj &#x3D; create_num(20)</span><br><span class="line"></span><br><span class="line">ret &#x3D; next(obj) </span><br><span class="line">print(ret)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">ret &#x3D; obj.send(&quot;hahaahha&quot;)  #等同于next()，不同的是可以传参</span><br><span class="line"># send()一般不会放到第一次启动生成器，如果非要这么做，那么传递None</span><br><span class="line"># 再次运行到yield a，将a的值赋给ret</span><br><span class="line">print(ret)</span><br></pre></td></tr></table></figure>

<h3 id="使用yield完成多任务"><a href="#使用yield完成多任务" class="headerlink" title="使用yield完成多任务"></a>使用yield完成多任务</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">import time</span><br><span class="line"></span><br><span class="line">def task_1():</span><br><span class="line">    while True:</span><br><span class="line">        print(&quot;---1---&quot;)</span><br><span class="line">        time.sleep(0.1)</span><br><span class="line">        yield</span><br><span class="line">        </span><br><span class="line">def task_2():</span><br><span class="line">    while True:</span><br><span class="line">        print(&quot;---2---&quot;)</span><br><span class="line">        time.sleep(0.1)</span><br><span class="line">        yield</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    t1 &#x3D; task_1()</span><br><span class="line">    t2 &#x3D; task_2()</span><br><span class="line">    # 先让t1运行一会，当t1中遇到yield的时候，返回此处</span><br><span class="line">    # 执行t2，当它遇到yield的时候，再次切换到t1中</span><br><span class="line">    # 这样t1&#x2F;t2&#x2F;t1&#x2F;t2的交替运行，最终实现了多任务...协程</span><br><span class="line">    while True:</span><br><span class="line">        next(t1)</span><br><span class="line">        next(t2)</span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h4 id="使用greenlet、gevent完成多任务"><a href="#使用greenlet、gevent完成多任务" class="headerlink" title="使用greenlet、gevent完成多任务"></a>使用greenlet、gevent完成多任务</h4><p>核心使用yield实现</p>
<p>$ pip3 install greenlet     # 安装greenlet</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">from greenlet import greenlet</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line">def test1():</span><br><span class="line">    while True:</span><br><span class="line">        print(&quot;---A---&quot;)</span><br><span class="line">        gr2.switch()</span><br><span class="line">        time.sleep(0.5)</span><br><span class="line">        </span><br><span class="line">def test2():</span><br><span class="line">    while True:</span><br><span class="line">        print(&quot;---B---&quot;)</span><br><span class="line">        gr1.switch()</span><br><span class="line">        time.sleep(0.5)</span><br><span class="line"></span><br><span class="line">gr1 &#x3D; greenlet(test1)</span><br><span class="line">gr2 &#x3D; greenlet(test2)</span><br><span class="line"></span><br><span class="line"># 切换到gr1中运行</span><br><span class="line">gr1.switch()</span><br></pre></td></tr></table></figure>

<p>$ pip3 install gevent</p>
<ul>
<li>依赖关系<br>协程 &lt;- 线程&lt;- 进程<br>遇到耗时操作进行切换</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">import gevent</span><br><span class="line"></span><br><span class="line">def f1(n):</span><br><span class="line">    for i in range(n):</span><br><span class="line">        print(gevent.getcurrent(), i)</span><br><span class="line">        gevent.sleep(0.5)</span><br><span class="line"></span><br><span class="line">def f2(n):</span><br><span class="line">    for i in range(n):</span><br><span class="line">        print(gevent.getcurrent(), i)</span><br><span class="line">        gevent.sleep(0.5)</span><br><span class="line"></span><br><span class="line">def f3(n):</span><br><span class="line">    for i in range(n):</span><br><span class="line">        print(gevent.getcurrent(), i)</span><br><span class="line">        gevent.sleep(0.5)</span><br><span class="line"></span><br><span class="line">g1 &#x3D; gevent.spawn(f1, 5)     #  生成yield对象 f:指定函数 5:指定传参 </span><br><span class="line">g2 &#x3D; gevent.spawn(f2, 5)</span><br><span class="line">g3 &#x3D; gevent.spawn(f3, 5)</span><br><span class="line">g1.join()   # 运行期间会耗时，自行切换到下一个对象</span><br><span class="line">g2.join()</span><br><span class="line">g3.join()</span><br></pre></td></tr></table></figure>

<h4 id="sleep补丁"><a href="#sleep补丁" class="headerlink" title="sleep补丁"></a>sleep补丁</h4><ul>
<li>协程使用代码示例<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">from gevent import monkey</span><br><span class="line">import gevent</span><br><span class="line">import random</span><br><span class="line">import time</span><br><span class="line"></span><br><span class="line"># 有耗时操作时需要</span><br><span class="line">monkey.patch_all()      # 将程序中用到的耗时操作的代码，换为gevent中自己实现的模块</span><br><span class="line"></span><br><span class="line">def coroutine_work(coroutine_name):</span><br><span class="line">    for i in range(10):</span><br><span class="line">        print(coroutine_name, i)</span><br><span class="line">        time.sleep(random.random()</span><br><span class="line"></span><br><span class="line"># 将多个join连接起来用一个元组实现</span><br><span class="line"># 等待元组中所有协程都完成后结束当前进程</span><br><span class="line">gevent.joinall([</span><br><span class="line">            gevent.spawn(coroutine_work, &quot;work1&quot;),</span><br><span class="line">            gevent.spawn(coroutine_work, &quot;work2&quot;)</span><br><span class="line">])</span><br></pre></td></tr></table></figure>

</li>
</ul>
<h4 id="案例-并发下载器"><a href="#案例-并发下载器" class="headerlink" title="案例-并发下载器"></a>案例-并发下载器</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">from gevent import monkey</span><br><span class="line">import gevent</span><br><span class="line">import urllib.request</span><br><span class="line"></span><br><span class="line">monkey.patch_all()</span><br><span class="line"></span><br><span class="line">def downloader(img_name, img_url):</span><br><span class="line">    req &#x3D; urllib.request.urlopen(img_orl)</span><br><span class="line">    </span><br><span class="line">    img_content &#x3D; req.read()</span><br><span class="line">    </span><br><span class="line">    with open(img_name, &quot;wb&quot;) as f:</span><br><span class="line">        f.write(img_content)</span><br><span class="line">        </span><br><span class="line">def main():</span><br><span class="line">    gevent.joinall([</span><br><span class="line">                gevent.spawn(downlaoder, &quot;1.jpg&quot;, &quot;http:&#x2F;&#x2F;url&quot;),</span><br><span class="line">                gevent.spawn(downlaoder, &quot;1.jpg&quot;, &quot;http:&#x2F;&#x2F;url&quot;)</span><br><span class="line">    ])</span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h4 id="进程、线程、协程对比"><a href="#进程、线程、协程对比" class="headerlink" title="进程、线程、协程对比"></a>进程、线程、协程对比</h4><ul>
<li>有一个老板想要开个工厂进行生产某件商品</li>
<li>他需要画一些财力物力制作一条生产线，这个生产线上有很多的器件以及材料这些所有的为了能够生产商品而准备的资源称之为：<strong>进程</strong></li>
<li>只有生产线程时不能够进行生产的，所以老板需要找个工人来进行生产，这个工人能够利用这些材料最终一步步的将商品制作出来，这个来做事情的工人称之为：<strong>线程</strong></li>
<li>这个老板为了提高生产率，想到3种方法：<ol>
<li>在这条生产线上多找些工人，一起来做商品，这样效率是成倍增长，即<strong>单进程 多线程</strong>方式</li>
<li>老板发现这条生产线上的工人不是越多越好，因为一条生产线的资源以及材料毕竟有限，所以老板又花了写财力物力购置了一条生产线，然后再招些工人，这样效率又再一步提高了，即<strong>多进程 多线程</strong>方式</li>
<li>老板发现，现在已经有了很多条生产线，并且每条生产线上已经有很多工人了（即程序是多进程的，每个进程中又有多个线程），为了再次提高效率，老板想了个损招，规定：如果某个员工在上班时，临时没事或者再等待某些条件（比如等待另一个工人生产完某道工序之后，他才能再次工作），那么这个员工就利用这个时间去做其他的事情，那么也就是说：如果一个线程等待某些条件，可以充分利用这个时间去做其他事情，其实这就是：<strong>协程</strong>方式</li>
</ol>
</li>
</ul>
<h5 id="简单总结"><a href="#简单总结" class="headerlink" title="简单总结"></a>简单总结</h5><ol>
<li>进程是资源分配的单位</li>
<li>线程是操作系统调度的单位</li>
<li>进程切换需要的资源最大，效率很低</li>
<li>线程切换需要的资源一般，效率一般（不考虑GIL的情况下）</li>
<li>协程切换任务资源很小，效率高</li>
<li>多进程、多线程根据CPU核数不一样可能是并行的，但是协程是在一个线程中，所以是并发。</li>
</ol>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/03-%E7%AE%80%E5%8D%95web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/03-%E7%AE%80%E5%8D%95web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0/" class="post-title-link" itemprop="url">简单web服务器python实现</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:15:03" itemprop="dateCreated datePublished" datetime="2020-03-06T14:15:03+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/03-%E7%AE%80%E5%8D%95web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0/" class="post-meta-item leancloud_visitors" data-flag-title="简单web服务器python实现" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line">import socket</span><br><span class="line">import re</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def service_client(new_socket):</span><br><span class="line">    &#39;&#39;&#39;为这个客户端返回数据&#39;&#39;&#39;</span><br><span class="line">    </span><br><span class="line">    # 1. 接受浏览器发送过来的请求，即http请求</span><br><span class="line">    # GET &#x2F; HTTP&#x2F;1.1</span><br><span class="line">    # .....</span><br><span class="line">    request &#x3D; new_socket.recv(1024).decode(&#39;utf-8&#39;)</span><br><span class="line">    </span><br><span class="line">    request_lines &#x3D; request.splitlines()</span><br><span class="line">    print(request_lines)</span><br><span class="line">    </span><br><span class="line">    file_name &#x3D; &#39;&#39;</span><br><span class="line">    ret &#x3D; re.match(r&quot;[^&#x2F;]+(&#x2F;[^ ]*)&quot;, request_lines[0])</span><br><span class="line">    if ret:</span><br><span class="line">        file_name &#x3D; re.group(1)</span><br><span class="line">        if file_name &#x3D;&#x3D; &quot;&#x2F;&quot;:</span><br><span class="line">            file_name &#x3D; &quot;&#x2F;index.html&quot;</span><br><span class="line">    </span><br><span class="line">    </span><br><span class="line">    # 2. 返回http格式的数据，给浏览器</span><br><span class="line">    </span><br><span class="line">    try:</span><br><span class="line">        f &#x3D; open(&quot;.&#x2F;html&#x2F;index.html&quot;,&quot;rb&quot;)</span><br><span class="line">    except:</span><br><span class="line">        response &#x3D; &#39;HTTP&#x2F;1.1 404 NOT FOUND\r\n&#39;</span><br><span class="line">        response +&#x3D; &#39;\r\n&#39;</span><br><span class="line">        response +&#x3D; &#39;----file not found----&#39;</span><br><span class="line">        new_socket.send(response.encode(&#39;utf-8&#39;))</span><br><span class="line">    else:</span><br><span class="line">        # 2.1 准备发送给浏览器的数据 ---header---</span><br><span class="line">        response &#x3D; &quot;HTTP&#x2F;1.1 200 OK\r\n&quot;</span><br><span class="line">        response +&#x3D; &quot;\r\n&quot;</span><br><span class="line">        # 2.2 准备发送给浏览器的数据 ---body---</span><br><span class="line">        html_content &#x3D; f.read()</span><br><span class="line">        f.close()</span><br><span class="line">        </span><br><span class="line">        # 3. 发送数据</span><br><span class="line">        # 3.1 发送header</span><br><span class="line">        new_socket.send(response.encode(&quot;utf-8&quot;))</span><br><span class="line">        # 3.2 发送body</span><br><span class="line">        new_socket.send(html_content)</span><br><span class="line">    </span><br><span class="line">    # 4. 关闭套接字</span><br><span class="line">    new_socket.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    &quot;&quot;&quot;用来完成整体的控制&quot;&quot;&quot;</span><br><span class="line">    # 1. 创建套接字</span><br><span class="line">    tcp_server_socket &#x3D; socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line">    </span><br><span class="line">    # 2. 绑定端口</span><br><span class="line">    tcp_server_socket.bind((&quot;&quot;, 7890))</span><br><span class="line">    </span><br><span class="line">    # 3. 变为监听套接字</span><br><span class="line">    tcp_server_socket.listen(128)</span><br><span class="line">    </span><br><span class="line">    while True:</span><br><span class="line">        # 4. 等待新客户端的链接</span><br><span class="line">        new_socket, client_addr &#x3D; tcp_server_socket.accept()</span><br><span class="line">        </span><br><span class="line">        # 5. 为这个客户端服务</span><br><span class="line">        service_client(new_socket)</span><br><span class="line">    </span><br><span class="line">    # 关闭监听套接字</span><br><span class="line">    tcp_server_socket.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure>

<h4 id="TCP三次握手、四次挥手"><a href="#TCP三次握手、四次挥手" class="headerlink" title="TCP三次握手、四次挥手"></a>TCP三次握手、四次挥手</h4>
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/04-%E5%B9%B6%E5%8F%91web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/04-%E5%B9%B6%E5%8F%91web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0/" class="post-title-link" itemprop="url">并发web服务器python实现</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:14:46" itemprop="dateCreated datePublished" datetime="2020-03-06T14:14:46+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/04-%E5%B9%B6%E5%8F%91web%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0/" class="post-meta-item leancloud_visitors" data-flag-title="并发web服务器python实现" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h4 id="单进程、单线程、非阻塞实现监听多个套接字"><a href="#单进程、单线程、非阻塞实现监听多个套接字" class="headerlink" title="单进程、单线程、非阻塞实现监听多个套接字"></a>单进程、单线程、非阻塞实现监听多个套接字</h4><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> socket</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"></span><br><span class="line">tcp_server_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  <span class="comment"># 创建套接字</span></span><br><span class="line">tcp_server_tcp.bind(<span class="string">""</span>,<span class="number">7890</span>)    <span class="comment"># 绑定端口</span></span><br><span class="line">tcp_server_tcp.listen()     <span class="comment"># 设为监听模式</span></span><br><span class="line">tcp_server_tcp.setblocking(<span class="literal">False</span>)   <span class="comment"># 设置套接字为非堵塞</span></span><br><span class="line"></span><br><span class="line">client_socket_list = list()</span><br><span class="line"></span><br><span class="line"><span class="keyword">while</span> <span class="literal">True</span>:</span><br><span class="line">    time.sleep(<span class="number">0.5</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        new_socket, new_addr = tcp_server_tcp.accept()</span><br><span class="line">    <span class="keyword">except</span> Exception <span class="keyword">as</span> ret:</span><br><span class="line">        print(<span class="string">"---没有新的客户端到来---"</span>)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        print(<span class="string">"---只要没有产生异常，那么也就意味着 来了一个新的客户端---"</span>)</span><br><span class="line">        new_socket.setblocking(<span class="literal">False</span>)  <span class="comment"># 设置套接字为非堵塞</span></span><br><span class="line">        client_socket_list.append(new_socket)</span><br><span class="line">        </span><br><span class="line">    <span class="keyword">for</span> client_socket <span class="keyword">in</span> client_socket_list:</span><br><span class="line">        <span class="keyword">try</span>:</span><br><span class="line">            client_socket.recv(<span class="number">1024</span>)    </span><br><span class="line">        <span class="keyword">except</span> Exception <span class="keyword">as</span> ret:</span><br><span class="line">            print(<span class="string">"---这个客户端没有发送过来数据---"</span>)</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">if</span> recv_data:</span><br><span class="line">                <span class="comment"># 对方发送过来数据</span></span><br><span class="line">                print(<span class="string">"---客户端发送过来了数据---"</span>)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="comment"># 对方调用close recv_data返回值为空</span></span><br><span class="line">                client_socket_list.remove(client_socket)</span><br><span class="line">                client_socket.close()</span><br><span class="line">                print(<span class="string">"客户端已经关闭。"</span>)</span><br></pre></td></tr></table></figure>

<h4 id="短连接-和-长连接"><a href="#短连接-和-长连接" class="headerlink" title="短连接 和 长连接"></a>短连接 和 长连接</h4><p><strong>长连接：</strong> 一个套接字获取多次数据<br><strong>短连接：</strong> 一个套接字只能获取一次数据</p>
<p>HTTP/1.0 是短连接<br>HTTP/1.1 是长连接</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line">import socket</span><br><span class="line">import re</span><br><span class="line"></span><br><span class="line">def service_client(new_socket, request):</span><br><span class="line">    &#39;&#39;&#39;为这个客户端返回数据&#39;&#39;&#39;</span><br><span class="line">    # 1. 处理浏览器发送过来的数据</span><br><span class="line">    request_lines &#x3D; requests.splitlines()</span><br><span class="line">    print(&quot;&quot;)</span><br><span class="line">    print(&quot;&gt;&quot;*20)</span><br><span class="line">    print(request_lines)</span><br><span class="line">    </span><br><span class="line">    file_name &#x3D; &quot;&quot;</span><br><span class="line">    ret &#x3D; re.match(r&quot;[^&#x2F;]+(&#x2F;[^ ]*)&quot;,request_lines[0])</span><br><span class="line">    if ret:</span><br><span class="line">        file_name &#x3D; ret.group()</span><br><span class="line">        if file_name &#x3D;&#x3D; &quot;&#x2F;&quot;:</span><br><span class="line">            file_name &#x3D; &quot;&#x2F;index.html&quot;</span><br><span class="line">    </span><br><span class="line">    # 2. 返回http格式的数据，给浏览器</span><br><span class="line">    </span><br><span class="line">    try:</span><br><span class="line">        f &#x3D; open(&quot;.&#x2F;html&quot; + file_name, &quot;rb&quot;)</span><br><span class="line">    except:</span><br><span class="line">        response &#x3D; &#39;HTTP&#x2F;1.1 404 NOT FOUND\r\n&#39; </span><br><span class="line">        response +&#x3D; &#39;\r\n&#39; </span><br><span class="line">        response +&#x3D; &#39;------file not found------&#39;</span><br><span class="line">        new_socket.send(response.encode(&#39;utf-8&#39;))</span><br><span class="line">    else:</span><br><span class="line">        html_content &#x3D; f.read()</span><br><span class="line">        f.close()</span><br><span class="line"></span><br><span class="line">        response_body &#x3D; html_content</span><br><span class="line">        </span><br><span class="line">        response_header &#x3D; &#39;HTTP&#x2F;1.1 200 OK\r\n&#39;</span><br><span class="line">        response_header +&#x3D; &#39;Content-Length:%d\r\n&#39; % len(response_body)</span><br><span class="line">        response_header +&#x3D; &#39;\r\n&#39;</span><br><span class="line"></span><br><span class="line">        response &#x3D; response_header.encode(&#39;utf-8&#39;) + response_body</span><br><span class="line">        </span><br><span class="line">        new_socket.send(response)</span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">    &#39;&#39;&#39;用来完成整体的控制&#39;&#39;&#39;</span><br><span class="line">    # 1. 创建套接字</span><br><span class="line">    tcp_server_tcp &#x3D; socket.socket(socket.AF_INET, socket.SOCK_STREAM)</span><br><span class="line">    tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)</span><br><span class="line">    </span><br><span class="line">    # 2. 绑定</span><br><span class="line">    tcp_server_socket.bind((&quot;&quot;, 7890))</span><br><span class="line">    </span><br><span class="line">    # 3. 变为监听套接字</span><br><span class="line">    tcp_server_socket.listen(128)</span><br><span class="line">    tcp_server_socket.setblocking(False)  # 设为非阻塞</span><br><span class="line">    </span><br><span class="line">    # --------------</span><br><span class="line">    # 创建一个epoll对象</span><br><span class="line">    epl &#x3D; select.epoll()</span><br><span class="line">    </span><br><span class="line">    # 将监听套接字对应的文件描述符fd注册到epoll中</span><br><span class="line">    epl.register(tcp_server_socket.fileno(), select.EPOLLIN)</span><br><span class="line">    # --------------</span><br><span class="line">    client_socket_list &#x3D; list()</span><br><span class="line">    while True:</span><br><span class="line">        # 4. 等待新客户端的链接</span><br><span class="line">        try:</span><br><span class="line">            new_socket, client_addr &#x3D; tcp_server_socket.accept()</span><br><span class="line">        except Exception as ret:</span><br><span class="line">            pass</span><br><span class="line">        else:</span><br><span class="line">            new_socket.setblocking(False)</span><br><span class="line">            client_socket_list.append(new_socket)</span><br><span class="line">            </span><br><span class="line">        for client_socket in client_socket_list:</span><br><span class="line">            try:</span><br><span class="line">                recv_data &#x3D; client_socket.recv(1024).decode(&#39;utf-8&#39;)</span><br><span class="line">            except Exception as ret:</span><br><span class="line">                pass</span><br><span class="line">            else:</span><br><span class="line">                if recv_data:</span><br><span class="line">                    service_client(client_socket, recv_data)</span><br><span class="line">                else:</span><br><span class="line">                    client_socket.close()</span><br><span class="line">                    client_socket_list.remove(client_socket)</span><br><span class="line">        </span><br><span class="line">        # 关闭套接字</span><br><span class="line">        tcp_server_socket.close()</span><br></pre></td></tr></table></figure>
<h4 id="epoll"><a href="#epoll" class="headerlink" title="epoll"></a>epoll</h4><p>单进程单线程多任务 由应用程序采用轮询实现<br>epoll是事件通知类型，由内核实现</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E5%AE%89%E8%A3%85%E9%BB%91%E8%8B%B9%E6%9E%9C%E5%B0%8F%E8%AE%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E5%AE%89%E8%A3%85%E9%BB%91%E8%8B%B9%E6%9E%9C%E5%B0%8F%E8%AE%B0/" class="post-title-link" itemprop="url">安装黑苹果记录</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:14:27" itemprop="dateCreated datePublished" datetime="2020-03-06T14:14:27+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E5%AE%89%E8%A3%85%E9%BB%91%E8%8B%B9%E6%9E%9C%E5%B0%8F%E8%AE%B0/" class="post-meta-item leancloud_visitors" data-flag-title="安装黑苹果记录" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="硬件平台：XiaoMi-Air12-5-m3-6y30-4G-128G"><a href="#硬件平台：XiaoMi-Air12-5-m3-6y30-4G-128G" class="headerlink" title="硬件平台：XiaoMi Air12.5 m3-6y30 4G+128G"></a>硬件平台：XiaoMi Air12.5 m3-6y30 4G+128G</h3><h4 id="完整备份win10系统"><a href="#完整备份win10系统" class="headerlink" title="完整备份win10系统"></a>完整备份win10系统</h4><p>建议使用win10系统自带备份功能。</p>
<h5 id="恢复win10系统"><a href="#恢复win10系统" class="headerlink" title="恢复win10系统"></a>恢复win10系统</h5><p>安装黑苹果会格掉整个盘，所以恢复时在U盘PE下使用系统镜像的install.wim软件左下角的恢复系统功能来进行恢复。</p>
<h4 id="准备文件"><a href="#准备文件" class="headerlink" title="准备文件"></a>准备文件</h4><ol>
<li>系统镜像         <a href="https://blog.daliansky.net/macOS-Mojave-10.14.4-18E226-official-version-with-Clover-4903-original-image.html" target="_blank" rel="noopener">mirror</a></li>
<li>刻盘软件etcher   <a href="https://www.balena.io/etcher/" target="_blank" rel="noopener">etcher</a></li>
<li>专用EFI          <a href="https://github.com/johnnync13/EFI-Xiaomi-Notebook-air-12-5.git" target="_blank" rel="noopener">EFI</a></li>
<li>win10备份U盘，16G以上</li>
<li>黑苹果系统U盘，8G以上</li>
</ol>
<h4 id="制作安装镜像"><a href="#制作安装镜像" class="headerlink" title="制作安装镜像"></a>制作安装镜像</h4><ol>
<li>格式化U盘</li>
<li>打开etcher软件</li>
<li>傻瓜式操作</li>
</ol>
<h4 id="替换EFI"><a href="#替换EFI" class="headerlink" title="替换EFI"></a>替换EFI</h4><p>因为镜像自带的EFI不兼容air12.5，所以我们要手动替换为专用EFI</p>
<p>win10磁盘管理工具可以进入U盘的EFI分区，将专用EFI中的EFI目录替换进U盘EFI分区中</p>
<h4 id="小米BIOS设置"><a href="#小米BIOS设置" class="headerlink" title="小米BIOS设置"></a>小米BIOS设置</h4><h5 id="升级BIOS版本至A05"><a href="#升级BIOS版本至A05" class="headerlink" title="升级BIOS版本至A05"></a>升级BIOS版本至A05</h5><p>A04版本的BIOS有关机不断掉的Bug，所以我们需要更新BIOS至A05</p>
<p>下载链接: <a href="http://bbs.xiaomi.cn/t-13100333" target="_blank" rel="noopener">BIOS-A05</a></p>
<p>按照帖子描述一键刷入即可。</p>
<h5 id="设置BIOS"><a href="#设置BIOS" class="headerlink" title="设置BIOS"></a>设置BIOS</h5><p>关闭Secure Boot模式，不然无法引导至macOS。</p>
<ol>
<li>开机按F2进BIOS</li>
<li>Security -&gt; Set Supervisor Password -&gt; Installed  # 不设置密码不能关闭</li>
<li>Securt Boot Mode -&gt; Disabled</li>
</ol>
<blockquote>
<p>开机按F12进入Boot Manager，设置从U盘启动。</p>
</blockquote>
<h4 id="安装黑苹果"><a href="#安装黑苹果" class="headerlink" title="安装黑苹果"></a>安装黑苹果</h4><p>首先进入Clover界面，Clover是一个黑苹果引导工具，因为macOS不支持非苹果机运行，所以我们要通过第三方工具来修正一系列底层参数，以正确的在非苹果机上引导macOS，该程序就是Clover</p>
<ol>
<li>屏幕亮起，进入Clover</li>
<li>选择 Boot OS X Install from XiaoMi</li>
<li>拷贝镜像到磁盘。。。。。。。。。</li>
</ol>
<p>进入macOS恢复模式，开始安装</p>
<ol>
<li>选择语言</li>
</ol>
<p>抹掉硬盘，确保你已经将所有的重要数据正确的备份到其他存储介质上。</p>
<ol>
<li>选中macOS实用工具 -&gt; 磁盘工具 -&gt; 左上角选项-显示所有设备</li>
<li>选择本地磁盘SSD Media -&gt; 上方功能栏-抹掉</li>
<li>选择默认的Mac OS扩展(日志型)  rename–&gt;Macintosh HD  -&gt; 抹掉</li>
<li>退出磁盘工具</li>
</ol>
<p>真正开始安装macOS</p>
<ol>
<li>安装macOS</li>
<li>进入安装界面</li>
<li>开始安装</li>
</ol>
<h4 id="安装第二阶段"><a href="#安装第二阶段" class="headerlink" title="安装第二阶段"></a>安装第二阶段</h4><p>等。。。。。。</p>
<h4 id="设置向导"><a href="#设置向导" class="headerlink" title="设置向导"></a>设置向导</h4><p>略</p>
<h4 id="替换EFI-1"><a href="#替换EFI-1" class="headerlink" title="替换EFI"></a>替换EFI</h4><p>因为EFI分区此时还在U盘上，所以我们需要将EFI文件拷贝到本地磁盘的EFI分区上</p>
<p>1.挂载EFI分区</p>
<p>打开终端，输入以下命令</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">$ diskutil list                # 查看磁盘分区表</span><br><span class="line">$ diskutil mount disk0s1        # 挂载磁盘FEI分区</span><br><span class="line">$ diskutil mount disk1s1        # 挂载U盘EFI分区</span><br><span class="line">$ find .                      # 打开Finder，进行替换操作</span><br></pre></td></tr></table></figure>

<ol start="2">
<li>合并EFI</li>
</ol>
<p>纯净安装macOS，没有Win10系统的EFI，不需要合并，此步省略</p>
<ol start="3">
<li>替换EFI</li>
</ol>
<p>将U盘EFI分区下的EFI目录复制到磁盘EFI分区下</p>
<h4 id="完善网卡驱动"><a href="#完善网卡驱动" class="headerlink" title="完善网卡驱动"></a>完善网卡驱动</h4><p>Mac本身不支持小米自带的网卡型号，无解，扩展槽无法添加WIFI无线网卡，只能选择外置USB网卡。</p>
<p>或者使用USB网络共享暂时上网 <a href="https://github.com/jwise/HoRNDIS/releases" target="_blank" rel="noopener">HoRNDIS</a>，下载安装即可。</p>
<p>USB连接手机，手机上打开热点，即可上网。</p>
<h4 id="开启HiDPI"><a href="#开启HiDPI" class="headerlink" title="开启HiDPI"></a>开启HiDPI</h4><p>1080P分辨率在12寸的屏幕上显示的字体特别小，所以有了开启HiDPI的需求</p>
<p>教程链接 <a href="https://zhih.me/one-key-hidpi/" target="_blank" rel="noopener">开启HiDPI</a><br>脚本下载链接 <a href="https://github.com/xzhih/one-key-hidpi.git" target="_blank" rel="noopener">下载HiDPI</a></p>
<h4 id="GitHub访问加速"><a href="#GitHub访问加速" class="headerlink" title="GitHub访问加速"></a>GitHub访问加速</h4><p>域名的IP地址在 <a href="https://www.ipaddress.com" target="_blank" rel="noopener">https://www.ipaddress.com</a> 查询</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$ sudo vim &#x2F;etc&#x2F;hosts</span><br><span class="line"># github</span><br><span class="line">192.30.253.112 GitHub.com</span><br><span class="line">185.199.108.153 assets-cdn.github.com</span><br><span class="line">151.101.185.194 github.global.ssl.fastly.net</span><br></pre></td></tr></table></figure>

<p>感谢提供专用EFI的作者<a href="https://github.com/johnnync13/" target="_blank" rel="noopener">johnnync13</a><br>感谢提供思路的<a href="http://bbs.xiaomi.cn/t-36526099" target="_blank" rel="noopener">etrock</a><br>感谢提供镜像的作者<a href="https://blog.daliansky.net" target="_blank" rel="noopener">黑果小兵</a></p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E5%A4%84%E7%90%86%E5%AD%97%E5%B9%95%E6%96%87%E4%BB%B6%EF%BC%8Cpython/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E5%A4%84%E7%90%86%E5%AD%97%E5%B9%95%E6%96%87%E4%BB%B6%EF%BC%8Cpython/" class="post-title-link" itemprop="url">使用正则处理字幕文件</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:13:49" itemprop="dateCreated datePublished" datetime="2020-03-06T14:13:49+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E5%A4%84%E7%90%86%E5%AD%97%E5%B9%95%E6%96%87%E4%BB%B6%EF%BC%8Cpython/" class="post-meta-item leancloud_visitors" data-flag-title="使用正则处理字幕文件" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <h3 id="使用python中的re模块处理YouTube字幕文件"><a href="#使用python中的re模块处理YouTube字幕文件" class="headerlink" title="使用python中的re模块处理YouTube字幕文件"></a>使用python中的re模块处理YouTube字幕文件</h3><p>状况：18个字幕文件，编码格式Window-1254，命名规律，按数字排序</p>
<p>需求：将字幕文件中的演讲词提取出来，剔除无用的字符，并合并为一个文件</p>
<h4 id="文件命名格式"><a href="#文件命名格式" class="headerlink" title="文件命名格式"></a>文件命名格式</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">ls tmp&#x2F;</span><br><span class="line">total 84K</span><br><span class="line">-rw-r--r-- 1 root root 3.1K Apr 22 14:50 02-Odyssey_Plans__The_Stages_of_Life.srt</span><br><span class="line">-rw-r--r-- 1 root root 4.6K Apr 22 14:51 03-Odyssey_Plans__What_is_an_Odyssey_Plan_.srt</span><br><span class="line">-rw-r--r-- 1 root root 2.5K Apr 22 14:51 04-Odyssey_Plans__What_does_an_Odyssey_Plan_Include_.srt</span><br><span class="line">-rw-r--r-- 1 root root 2.9K Apr 22 14:52 05-Odyssey_Plans__Presentation_Format.srt</span><br><span class="line">-rw-r--r-- 1 root root 1.5K Apr 22 14:52 06-Odyssey_Plans__5-Year_Timelines.srt</span><br><span class="line">-rw-r--r-- 1 root root 1.2K Apr 22 14:53 07-Odyssey_Plans__6-Word_Title.srt</span><br><span class="line">-rw-r--r-- 1 root root 2.0K Apr 22 14:53 08-Odyssey_Plans__Designing_3_Timelines.srt</span><br><span class="line">-rw-r--r-- 1 root root 1.9K Apr 22 14:54 09-Odyssey_Plans__Building_your_10-year_timeline.srt</span><br><span class="line">-rw-r--r-- 1 root root 1.3K Apr 22 14:54 10-Odyssey_Plans__Choosing_a_Symbol.srt</span><br><span class="line">-rw-r--r-- 1 root root 3.2K Apr 22 14:54 11-Odyssey_Plans__Creating_a_Dashboard.srt</span><br><span class="line">-rw-r--r-- 1 root root 1013 Apr 22 14:54 12-Odyssey_Plans__Identifying_Questions.srt</span><br><span class="line">-rw-r--r-- 1 root root 1.6K Apr 22 14:55 13-Odyssey_Plans__Writing_a_Thank-You_note.srt</span><br><span class="line">-rw-r--r-- 1 root root 2.8K Apr 22 14:55 14-Odyssey_Plans__How_to_&#39;Prototype&#39;_your_Odysseys.srt</span><br><span class="line">-rw-r--r-- 1 root root 4.7K Apr 22 14:55 15-Odyssey_Plans__Prototype_Conversations_and_Experiences.srt</span><br><span class="line">-rw-r--r-- 1 root root 3.7K Apr 22 14:55 16-Odyssey_Plans__How_often_to_design_an_Odyssey_plan.srt</span><br><span class="line">-rw-r--r-- 1 root root 3.8K Apr 22 14:56 17-Odyssey_Plans__Insights_and_Takeaways.srt</span><br><span class="line">-rw-r--r-- 1 root root 3.2K Apr 24 19:55 01-Odyssey_Plans__What_are_the_Odyssey_Years_.srt</span><br><span class="line">-rw-r--r-- 1 root root 5.8K Apr 24 20:05 18-Odyssey_Plans__Applying_Designers&#39;_Mindsets.srt</span><br></pre></td></tr></table></figure>
<h4 id="文件内容格式"><a href="#文件内容格式" class="headerlink" title="文件内容格式"></a>文件内容格式</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">1</span><br><span class="line">00:00:03,590 --&gt; 00:00:04,710</span><br><span class="line">My name is Bill Burnett.</span><br><span class="line"></span><br><span class="line">2</span><br><span class="line">00:00:04,710 --&gt; 00:00:07,460</span><br><span class="line">I&#39;m one of the co-authors</span><br><span class="line">of Designing Your Life,</span><br><span class="line"></span><br><span class="line">3</span><br><span class="line">00:00:07,460 --&gt; 00:00:09,410</span><br><span class="line">How to Live a</span><br><span class="line">Well-Lived Joyful Life.</span><br><span class="line"></span><br><span class="line">......</span><br></pre></td></tr></table></figure>
<h4 id="思路分析"><a href="#思路分析" class="headerlink" title="思路分析"></a>思路分析</h4><ul>
<li>获取所有文件名存入列表  &lt;–  方便循环进行文件操作</li>
<li>然后用正则匹配演讲词并打印出来  &lt;– 剔除无用字符</li>
<li>执行脚本并将输出重定向到一个新文件 &lt;– 合并为一个文件</li>
</ul>
<h4 id="实现代码"><a href="#实现代码" class="headerlink" title="实现代码"></a>实现代码</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"># Script_name: merge_final.py</span><br><span class="line"></span><br><span class="line">import re</span><br><span class="line">import os</span><br><span class="line"></span><br><span class="line"># 字幕文件所在目录</span><br><span class="line">dir &#x3D; &quot;&#x2F;root&#x2F;tmp&#x2F;&quot;</span><br><span class="line"></span><br><span class="line">def process(filename):</span><br><span class="line">        &#39;&#39;&#39;对文件进行操作&#39;&#39;&#39;</span><br><span class="line">        print(filename)</span><br><span class="line">        </span><br><span class="line">        with open(dir+filename, &#39;r&#39;, encode&#x3D;&#39;utf-8&#39;) as f:       # 打开文件</span><br><span class="line">                lines &#x3D; f.readlines()       # 按行读取整个文件，存入列表</span><br><span class="line">                </span><br><span class="line">                for line in lines:</span><br><span class="line">                        # 剔除无用字符</span><br><span class="line">                        lrc &#x3D; re.search(r&#39;^\D.*[a-z.]&#39;, line) </span><br><span class="line">                        if lrc: </span><br><span class="line">                                print(lrc.group()) </span><br><span class="line">        </span><br><span class="line">        print(&quot;--------------------&quot;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">def main():</span><br><span class="line">        filelist &#x3D; os.listdir(dir)      # 获取目录下所有的文件名称</span><br><span class="line">        filelist.sort()                 # 按照数字排序</span><br><span class="line">        </span><br><span class="line">        for filename in filelist:</span><br><span class="line">                process(filename)       # 将文件名传过去</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">if __name__ &#x3D;&#x3D; &quot;__main__&quot;:</span><br><span class="line">        main()</span><br></pre></td></tr></table></figure>
<h4 id="执行脚本"><a href="#执行脚本" class="headerlink" title="执行脚本"></a>执行脚本</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root@dayday ~]# python merge_final.py &gt; lecture.txt</span><br></pre></td></tr></table></figure>

<h4 id="知识点整理"><a href="#知识点整理" class="headerlink" title="知识点整理"></a>知识点整理</h4><p><strong>1. 编码格式问题</strong></p>
<p>在读取中文的情况下，通常会遇到一些编码的问题，但是首先需要了解目前的编码方式是什么，然后再用decode或者encode去编码和解码，下面是使用chardet库来查看编码方式的。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">import chardet</span><br><span class="line"></span><br><span class="line">path &#x3D; &quot;E:&#x2F;t.csv&quot;</span><br><span class="line">f &#x3D; open(path,&#39;rb&#39;)</span><br><span class="line"></span><br><span class="line">data &#x3D; f.read()</span><br><span class="line">print(chardet.detect(data))</span><br></pre></td></tr></table></figure>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@dayday ~]# python test.py</span><br><span class="line">&#123;&#39;encoding&#39;: &#39;GB2312&#39;, &#39;confidence&#39;: 0.99, &#39;language&#39;: &#39;Chinese&#39;&#125;</span><br></pre></td></tr></table></figure>
<p>当时的字幕是从<a href="http://downsub.com/" target="_blank" rel="noopener">downsub.com</a>网站下载的，编码格式是Windows-1254格式，在Python进行文件操作时总是报错，偷懒在notepad++下手动更改编码格式为utf-8，当然也可以用Python脚本实现。</p>
<p><strong>2. 导入目录下所有文件的名称&amp;排序问题</strong></p>
<p>这个就是知识没掌握的问题了，在此记录。os是个强大的模块！</p>
<p><strong>3. 正则语法</strong></p>
<p>好多语法格式都不熟练，一边调试一边查<a href="runoob.com">runoob.com</a>，着实耗时间，需反复练习！</p>
<p><strong>4. re.match()返回值问题</strong></p>
<p>re.match()匹配成功返回re.match()对象，可用.group()方法提取字符串；匹配失败返回None。</p>
<p>文件时是按行读取的，因此循环对行进行正则匹配，返回的结果中穿插着None和re.match对象，而None调用.group()方法会报错，所以在这简单的用if过滤掉了None。</p>
<p>在敲这篇记录时突然想起，应该可以用Python的异常处理过滤掉报错，改天试试看</p>
<p><strong>5. 养成随手记录的习惯</strong></p>
<p>在整个解决过程中，查了很多资料，但没有随时记下来，解决完问题做记录的时候有些问题都忘记了！</p>

      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

        
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block home" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="daydaychen.github.io/2020/03/06/hello-world/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="CT">
      <meta itemprop="description" content="this is a desc.">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="宁静致远">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          
            <a href="/2020/03/06/hello-world/" class="post-title-link" itemprop="url">Hello World</a>
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>

              <time title="创建时间：2020-03-06 14:07:03" itemprop="dateCreated datePublished" datetime="2020-03-06T14:07:03+08:00">2020-03-06</time>
            </span>

          
            <span id="/2020/03/06/hello-world/" class="post-meta-item leancloud_visitors" data-flag-title="Hello World" title="阅读次数">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">阅读次数：</span>
              <span class="leancloud-visitors-count"></span>
            </span>
  
  

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
          <p>Welcome to <a href="https://hexo.io/" target="_blank" rel="noopener">Hexo</a>! This is your very first post. Check <a href="https://hexo.io/docs/" target="_blank" rel="noopener">documentation</a> for more info. If you get any problems when using Hexo, you can find the answer in <a href="https://hexo.io/docs/troubleshooting.html" target="_blank" rel="noopener">troubleshooting</a> or you can ask me on <a href="https://github.com/hexojs/hexo/issues" target="_blank" rel="noopener">GitHub</a>.</p>
<h2 id="Quick-Start"><a href="#Quick-Start" class="headerlink" title="Quick Start"></a>Quick Start</h2><h3 id="Create-a-new-post"><a href="#Create-a-new-post" class="headerlink" title="Create a new post"></a>Create a new post</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ hexo new <span class="string">"My New Post"</span></span><br></pre></td></tr></table></figure>

<p>More info: <a href="https://hexo.io/docs/writing.html" target="_blank" rel="noopener">Writing</a></p>
          <!--noindex-->
            <div class="post-button">
              <a class="btn" href="/2020/03/06/hello-world/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          <!--/noindex-->
        
      
    </div>

    
    
    
      <footer class="post-footer">
        <div class="post-eof"></div>
      </footer>
  </article>
  
  
  

  </div>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span>
  </nav>



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="CT"
      src="/images/avatar.gif">
  <p class="site-author-name" itemprop="name">CT</p>
  <div class="site-description" itemprop="description">this is a desc.</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">16</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">5</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/daydaychen" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;daydaychen" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:ctt0120@foxmail.com" title="E-Mail → mailto:ctt0120@foxmail.com" rel="noopener" target="_blank"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
      </span>
  </div>
  <div class="cc-license motion-element" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="/images/cc-by-nc-sa.svg" alt="Creative Commons"></a>
  </div>



      </div>
        <div class="back-to-top motion-element">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">CT</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> 强力驱动 v4.2.0
  </div>
  <span class="post-meta-divider">|</span>
  <div class="theme-info">主题 – <a href="https://theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Gemini</a> v7.7.2
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="//cdn.jsdelivr.net/npm/animejs@3.1.0/lib/anime.min.js"></script>
  <script src="//cdn.jsdelivr.net/gh/theme-next/theme-next-pjax@0/pjax.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/medium-zoom@1/dist/medium-zoom.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/lozad@1/dist/lozad.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/pangu@4/dist/browser/pangu.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/velocity-animate@1/velocity.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/velocity-animate@1/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>

  <script>
var pjax = new Pjax({
  selectors: [
    'head title',
    '#page-configurations',
    '.content-wrap',
    '.post-toc-wrap',
    '#pjax'
  ],
  switches: {
    '.post-toc-wrap': Pjax.switches.innerHTML
  },
  analytics: false,
  cacheBust: false,
  scrollTo : !CONFIG.bookmark.enable
});

window.addEventListener('pjax:success', () => {
  document.querySelectorAll('script[pjax], script#page-configurations, #pjax script').forEach(element => {
    var code = element.text || element.textContent || element.innerHTML || '';
    var parent = element.parentNode;
    parent.removeChild(element);
    var script = document.createElement('script');
    if (element.id) {
      script.id = element.id;
    }
    if (element.className) {
      script.className = element.className;
    }
    if (element.type) {
      script.type = element.type;
    }
    if (element.src) {
      script.src = element.src;
      // Force synchronous loading of peripheral JS.
      script.async = false;
    }
    if (element.getAttribute('pjax') !== null) {
      script.setAttribute('pjax', '');
    }
    if (code !== '') {
      script.appendChild(document.createTextNode(code));
    }
    parent.appendChild(script);
  });
  NexT.boot.refresh();
  // Define Motion Sequence & Bootstrap Motion.
  if (CONFIG.motion.enable) {
    NexT.motion.integrator
      .init()
      .add(NexT.motion.middleWares.subMenu)
      .add(NexT.motion.middleWares.postList)
      .bootstrap();
  }
  NexT.utils.updateSidebarPosition();
});
</script>




  




  
<script src="/js/local-search.js"></script>













    <div id="pjax">
  

  


<script>
NexT.utils.loadComments(document.querySelector('#valine-comments'), () => {
  NexT.utils.getScript('//cdn.jsdelivr.net/npm/valine@1/dist/Valine.min.js', () => {
    var GUEST = ['nick', 'mail', 'link'];
    var guest = 'nick,mail,link';
    guest = guest.split(',').filter(item => {
      return GUEST.includes(item);
    });
    new Valine({
      el         : '#valine-comments',
      verify     : false,
      notify     : false,
      appId      : '9bBjpz3HRuKNuKNp7T27dFsT-gzGzoHsz',
      appKey     : 'k2pzqGWjkjrKxlFLQ3O0oqDn',
      placeholder: "Just go go",
      avatar     : 'robohash',
      meta       : guest,
      pageSize   : '10' || 10,
      visitor    : true,
      lang       : 'zh-cn' || 'zh-cn',
      path       : location.pathname,
      recordIP   : false,
      serverURLs : ''
    });
  }, window.Valine);
});
</script>

    </div>
</body>
</html>
